@import '../core/theming/theming';
@import '../core/style/elevation';
@import '../core/style/checkbox-common';
@import '../core/ripple/ripple';

// Manual calculation done on SVG
$_mat-checkbox-mark-path-length: 22.910259;
$_mat-checkbox-indeterminate-checked-easing-function: cubic-bezier(0.14, 0, 0, 1);

// The ripple size of the checkbox
$_mat-checkbox-ripple-size: 15px;

// The amount of spacing between the checkbox and its label.
$_mat-checkbox-item-spacing: $mat-toggle-padding;

// The width of the line used to draw the checkmark / mixedmark.
$_mat-checkbox-mark-stroke-size: 2 / 15 * $mat-checkbox-size !default;


// Fades in the background of the checkbox when it goes from unchecked -> {checked,indeterminate}.
@keyframes mat-checkbox-fade-in-background {
  0% {
    opacity: 0;
  }

  50% {
    opacity: 1;
  }
}

// Fades out the background of the checkbox when it goes from {checked,indeterminate} -> unchecked.
@keyframes mat-checkbox-fade-out-background {
  0%, 50% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

// "Draws" in the checkmark when the checkbox goes from unchecked -> checked.
@keyframes mat-checkbox-unchecked-checked-checkmark-path {
  0%, 50% {
    stroke-dashoffset: $_mat-checkbox-mark-path-length;
  }

  50% {
    animation-timing-function: $mat-linear-out-slow-in-timing-function;
  }

  100% {
    stroke-dashoffset: 0;
  }
}

// Horizontally expands the mixedmark when the checkbox goes from unchecked -> indeterminate.
@keyframes mat-checkbox-unchecked-indeterminate-mixedmark {
  0%, 68.2% {
    transform: scaleX(0);
  }

  68.2% {
    animation-timing-function: cubic-bezier(0, 0, 0, 1);
  }

  100% {
    transform: scaleX(1);
  }
}

// "Erases" the checkmark when the checkbox goes from checked -> unchecked.
@keyframes mat-checkbox-checked-unchecked-checkmark-path {
  from {
    animation-timing-function: $mat-fast-out-linear-in-timing-function;
    stroke-dashoffset: 0;
  }

  to {
    stroke-dashoffset: $_mat-checkbox-mark-path-length * -1;
  }
}


// Rotates and fades out the checkmark when the checkbox goes from checked -> indeterminate. This
// animation helps provide the illusion of the checkmark "morphing" into the mixedmark.
@keyframes mat-checkbox-checked-indeterminate-checkmark {
  from {
    animation-timing-function: $mat-linear-out-slow-in-timing-function;
    opacity: 1;
    transform: rotate(0deg);
  }

  to {
    opacity: 0;
    transform: rotate(45deg);
  }
}

// Rotates and fades the checkmark back into position when the checkbox goes from indeterminate ->
// checked. This animation helps provide the illusion that the mixedmark is "morphing" into the
// checkmark.
@keyframes mat-checkbox-indeterminate-checked-checkmark {
  from {
    animation-timing-function: $_mat-checkbox-indeterminate-checked-easing-function;
    opacity: 0;
    transform: rotate(45deg);
  }

  to {
    opacity: 1;
    transform: rotate(360deg);
  }
}

// Rotates and fades in the mixedmark when the checkbox goes from checked -> indeterminate. This
// animation, similar to mat-checkbox-checked-indeterminate-checkmark, helps provide an illusion
// of "morphing" from checkmark -> mixedmark.
@keyframes mat-checkbox-checked-indeterminate-mixedmark {
  from {
    animation-timing-function: $mat-linear-out-slow-in-timing-function;
    opacity: 0;
    transform: rotate(-45deg);
  }

  to {
    opacity: 1;
    transform: rotate(0deg);
  }
}

// Rotates and fades out the mixedmark when the checkbox goes from indeterminate -> checked. This
// animation, similar to mat-checkbox-indeterminate-checked-checkmark, helps provide an illusion
// of "morphing" from mixedmark -> checkmark.
@keyframes mat-checkbox-indeterminate-checked-mixedmark {
  from {
    animation-timing-function: $_mat-checkbox-indeterminate-checked-easing-function;
    opacity: 1;
    transform: rotate(0deg);
  }

  to {
    opacity: 0;
    transform: rotate(315deg);
  }
}


// Horizontally collapses and fades out the mixedmark when the checkbox goes from indeterminate ->
// unchecked.
@keyframes mat-checkbox-indeterminate-unchecked-mixedmark {
  0% {
    animation-timing-function: linear;
    opacity: 1;
    transform: scaleX(1);
  }

  32.8%, 100% {
    opacity: 0;
    transform: scaleX(0);
  }
}

// Applied to elements that cover the checkbox's entire inner container.
%mat-checkbox-cover-element {
  bottom: 0;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}

// Applied to elements that are considered "marks" within the checkbox, e.g. the checkmark and
// the mixedmark.
%mat-checkbox-mark {
  $width-padding-inset: 2 * $mat-checkbox-border-width;
  width: calc(100% - #{$width-padding-inset});
}

// Applied to elements that appear to make up the outer box of the checkmark, such as the frame
// that contains the border and the actual background element that contains the marks.
%mat-checkbox-outer-box {
  @extend %mat-checkbox-cover-element;
  border-radius: 2px;
  box-sizing: border-box;
  pointer-events: none;
}

.mat-checkbox {
  // Animation
  transition: background $swift-ease-out-duration $swift-ease-out-timing-function,
              mat-elevation-transition-property-value();

  cursor: pointer;
}

.mat-checkbox-layout {
  // `cursor: inherit` ensures that the wrapper element gets the same cursor as the mat-checkbox
  // (e.g. pointer by default, regular when disabled), instead of the browser default.
  cursor: inherit;
  align-items: baseline;
  vertical-align: middle;
  display: inline-flex;
}

.mat-checkbox-inner-container {
  display: inline-block;
  height: $mat-checkbox-size;
  line-height: 0;
  margin: auto;
  margin-right: $_mat-checkbox-item-spacing;
  order: 0;
  position: relative;
  vertical-align: middle;
  white-space: nowrap;
  width: $mat-checkbox-size;
  flex-shrink: 0;

  [dir='rtl'] & {
    margin: {
      left: $_mat-checkbox-item-spacing;
      right: auto;
    }
  }
}

.mat-checkbox-inner-container-no-side-margin {
  margin: {
    left: 0;
    right: 0;
  }
}

.mat-checkbox-frame {
  @extend %mat-checkbox-outer-box;

  background-color: transparent;
  transition:
      border-color $mat-checkbox-transition-duration $mat-linear-out-slow-in-timing-function;
  border: {
    width: $mat-checkbox-border-width;
    style: solid;
  }
}

.mat-checkbox-background {
  @extend %mat-checkbox-outer-box;

  align-items: center;
  display: inline-flex;
  justify-content: center;
  transition: background-color $mat-checkbox-transition-duration
                  $mat-linear-out-slow-in-timing-function,
              opacity $mat-checkbox-transition-duration $mat-linear-out-slow-in-timing-function;
}

.mat-checkbox-checkmark {
  @extend %mat-checkbox-cover-element;
  @extend %mat-checkbox-mark;

  width: 100%;
}

.mat-checkbox-checkmark-path {
  stroke: {
    dashoffset: $_mat-checkbox-mark-path-length;
    dasharray: $_mat-checkbox-mark-path-length;
    width: $_mat-checkbox-mark-stroke-size;
  }
}

.mat-checkbox-mixedmark {
  @extend %mat-checkbox-mark;

  height: floor($_mat-checkbox-mark-stroke-size);
  opacity: 0;
  transform: scaleX(0) rotate(0deg);
}

.mat-checkbox-label-before {
  .mat-checkbox-inner-container {
    order: 1;
    margin: {
      left: $_mat-checkbox-item-spacing;
      right: auto;
    }

    [dir='rtl'] & {
      margin: {
        left: auto;
        right: $_mat-checkbox-item-spacing;
      }
    }
  }
}

.mat-checkbox-checked {
  .mat-checkbox-checkmark {
    opacity: 1;
  }

  .mat-checkbox-checkmark-path {
    stroke-dashoffset: 0;
  }

  .mat-checkbox-mixedmark {
    transform: scaleX(1) rotate(-45deg);
  }
}

.mat-checkbox-indeterminate {
  .mat-checkbox-checkmark {
    opacity: 0;
    transform: rotate(45deg);
  }

  .mat-checkbox-checkmark-path {
    stroke-dashoffset: 0;
  }

  .mat-checkbox-mixedmark {
    opacity: 1;
    transform: scaleX(1) rotate(0deg);
  }
}


.mat-checkbox-unchecked {
  .mat-checkbox-background {
    background-color: transparent;
  }
}

.mat-checkbox-disabled {
  cursor: default;
}

.mat-checkbox-anim {
  $indeterminate-change-duration: 500ms;

  &-unchecked-checked {
    .mat-checkbox-background {
      animation: $mat-checkbox-transition-duration * 2 linear 0ms mat-checkbox-fade-in-background;
    }

    .mat-checkbox-checkmark-path {
      // Instead of delaying the animation, we simply multiply its length by 2 and begin the
      // animation at 50% in order to prevent a flash of styles applied to a checked checkmark
      // as the background is fading in before the animation begins.
      animation:
        $mat-checkbox-transition-duration * 2 linear 0ms mat-checkbox-unchecked-checked-checkmark-path;
    }
  }

  &-unchecked-indeterminate {
    .mat-checkbox-background {
      animation: $mat-checkbox-transition-duration * 2 linear 0ms mat-checkbox-fade-in-background;
    }

    .mat-checkbox-mixedmark {
      animation:
        $mat-checkbox-transition-duration linear 0ms mat-checkbox-unchecked-indeterminate-mixedmark;
    }
  }

  &-checked-unchecked {
    .mat-checkbox-background {
      animation: $mat-checkbox-transition-duration * 2 linear 0ms mat-checkbox-fade-out-background;
    }

    .mat-checkbox-checkmark-path {
      animation:
        $mat-checkbox-transition-duration linear 0ms mat-checkbox-checked-unchecked-checkmark-path;
    }
  }

  &-checked-indeterminate {
    .mat-checkbox-checkmark {
      animation:
        $mat-checkbox-transition-duration linear 0ms mat-checkbox-checked-indeterminate-checkmark;
    }

    .mat-checkbox-mixedmark {
      animation:
        $mat-checkbox-transition-duration linear 0ms mat-checkbox-checked-indeterminate-mixedmark;
    }
  }

  &-indeterminate-checked {
    .mat-checkbox-checkmark {
      animation:
        $indeterminate-change-duration linear 0ms mat-checkbox-indeterminate-checked-checkmark;
    }

    .mat-checkbox-mixedmark {
      animation:
        $indeterminate-change-duration linear 0ms mat-checkbox-indeterminate-checked-mixedmark;
    }
  }

  &-indeterminate-unchecked {
    .mat-checkbox-background {
      animation: $mat-checkbox-transition-duration * 2 linear 0ms mat-checkbox-fade-out-background;
    }

    .mat-checkbox-mixedmark {
      animation:
        $indeterminate-change-duration * 0.6 linear 0ms
        mat-checkbox-indeterminate-unchecked-mixedmark;
    }
  }
}

.mat-checkbox-input {
  // Move the input to the bottom and in the middle.
  // Visual improvement to properly show browser popups when being required.
  bottom: 0;
  left: 50%;
}

.mat-checkbox-ripple {
  position: absolute;
  left: -$_mat-checkbox-ripple-size;
  top: -$_mat-checkbox-ripple-size;
  right: -$_mat-checkbox-ripple-size;
  bottom: -$_mat-checkbox-ripple-size;
  border-radius: 50%;
  z-index: 1;
  pointer-events: none;
}
